package com.allqj.sfx.infrastructure;

import com.allqj.sfx.infrastructure.exceptions.BusinessException;
import com.allqj.sfx.infrastructure.vo.ResultVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * @author sjw
 * @className GlobalExceptionHandler
 * @date 2022/7/19 8:42
 * @description: 全局异常处理
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    private String exceptionToString(Exception e) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        return "\r\n" + sw.toString() + "\r\n";
    }

    private HttpServletRequest getRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return attributes.getRequest();
    }

    @ExceptionHandler({Exception.class})
    @ResponseStatus(HttpStatus.OK)
    public ResultVO handleException(Exception e) {
        String msg = exceptionToString(e);
        HttpServletRequest request = this.getRequest();
        logger.error("{} {} {} {} {} {} {}", request.getMethod(), request.getRequestURL(), request.getRequestURI(), HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getClass(), e.getMessage(), msg);
        return ResultVO.Instance(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
    }

    @ExceptionHandler({BusinessException.class})
    @ResponseStatus(HttpStatus.OK)
    public ResultVO handleException(BusinessException e) {
        String msg = exceptionToString(e);
        HttpServletRequest request = this.getRequest();
        logger.error("{} {} {} {} {} {} {}", request.getMethod(), request.getRequestURL(), request.getRequestURI(), HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getClass(), e.getMessage(), msg);
        return ResultVO.Instance(e.getStatusCode(), e.getMessage());
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.OK)
    public ResultVO handleException(MethodArgumentNotValidException e) {
        String msg = exceptionToString(e);
        HttpServletRequest request = this.getRequest();
        logger.error("{} {} {} {} {} {} {}", request.getMethod(), request.getRequestURL(), request.getRequestURI(), HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getClass(), e.getMessage(), msg);
        return ResultVO.Instance(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    }
}
